Converting source code into executable code is a two step process. In a first step, the source code is compiled into what is known as an object file. In a second step, the object file is processed by a linker which may combine the object file with other objects to generate the final executable file.
The linker will resolve references to undefined symbols by finding which other object defines a symbol in question, and replacing placeholders with the symbol's address. Since a compiler generally does not know where an object will reside in the program's address space, it assumes a fixed base location (for example, zero). The linker therefore arranges the objects in a program's address space by relocating code provided by each object file that assumes a specific base address to another base. Relocating machine code may involve re-targeting of absolute jumps, loads and stores. Since the compiler does not know what address it will ultimately need to load at the time of compiling, many compilers will assume a maximum address size requiring 64 bits unless explicitly told otherwise by the programmer/user. Other compilers may assume a different maximum size, depending on the processor architecture.
In reduced instruction set computing (RISC) processors, a 32 bit machine-language instruction may include a certain number of bits of a constant value for use as data. So long as the constant value can be expressed in the number of data bits made available by the instruction format, considerable time may be saved by having the number incorporated into the instruction itself. In particular, this avoids having to load the numbers from memory or registers. However, larger numbers require multiple instructions to load. In this case, a number is segmented into multiple parts and each part is loaded separately.
In the case where the constant value to be loaded is an address, the compiler may generate code that assumes a larger address then is actually eventually assigned by the linker. Thus, additional unnecessary instructions are incorporated into the final code which adversely affects the program size and speed of execution.
There is a continuing need to improve the efficiency and speed of execution of computer software. It would therefore be desirable to develop a system and method for mitigating the inefficiencies identified above.